home *** CD-ROM | disk | FTP | other *** search
/ Libris Britannia 4 / science library(b).zip / science library(b) / CUGUK / COMMS / C101.ZIP / UUPC11XS.ZIP / UUCICO / DCPSYS.C < prev    next >
C/C++ Source or Header  |  1992-12-11  |  35KB  |  960 lines

  1. /*--------------------------------------------------------------------*/
  2. /*    d c p s y s . c                                                 */
  3. /*                                                                    */
  4. /*    System support functions for UUCICO                             */
  5. /*                                                                    */
  6. /*    Changes Copyright (c) 1990-1992 by Kendra Electronic            */
  7. /*    Wonderworks.                                                    */
  8. /*                                                                    */
  9. /*    Changes Copyright (c) 1989 by Andrew H. Derbyshire.             */
  10. /*                                                                    */
  11. /*    All rights reserved except those explicitly granted by the      */
  12. /*    UUPC/extended license agreement.                                */
  13. /*                                                                    */
  14. /*    Copyright (c) Richard H. Lamb 1985, 1986, 1987                  */
  15. /*    Changes Copyright (c) Stuart Lynne 1987                         */
  16. /*                                                                    */
  17. /* Updated:                                                           */
  18. /*                                                                    */
  19. /*    13May89  - Modified checkname to only examine first token of    */
  20. /*               name.                                                */
  21. /*               Modified rmsg to initialize input character before   */
  22. /*               use.                                                 */
  23. /*    16May89  - Moved checkname to router.c - ahd                    */
  24. /*    17May89  - Wrote real checktime() - ahd                         */
  25. /*    17May89  - Changed getsystem to return 'I' instead of 'G'       */
  26. /*    25Jun89  - Added Reach-Out America to keyword table for         */
  27. /*               checktime                                            */
  28. /*    22Sep89  - Password file support for hosts                      */
  29. /*    25Sep89  - Change 'ExpectStr' message to debuglevel 2           */
  30. /*    01Jan90  - Revert 'ExpectStr' message to debuglevel 1           */
  31. /*    28Jan90  - Alter callup() to use table driven modem driver.     */
  32. /*               Add direct(), qx() procedures.                       */
  33. /*    8 Jul90  - Add John DuBois's expectstr() routine to fix         */
  34. /*               problems with long input buffers.                    */
  35. /*    11Nov90  - Delete QX support, add ddelay, ssleep calls          */
  36. /*    21Sep92  - Insure system system name and time do not crash      */
  37. /*               UUCICO - from the original fix by Eugene             */
  38. /*               Nesterenko, Moscow, Russia                           */
  39. /*--------------------------------------------------------------------*/
  40.  
  41. /*
  42.  *     $Id: DCPSYS.C 1.10 1992/12/11 12:45:11 ahd Exp $
  43.  *
  44.  *     $Log: DCPSYS.C $
  45.  * Revision 1.10  1992/12/11  12:45:11  ahd
  46.  * Shorten remote display to improve OS/2 windowed scrolling
  47.  *
  48.  * Revision 1.9  1992/12/01  04:37:03  ahd
  49.  * Modify *nbstime call restrictions to make it less agressive
  50.  *
  51.  * Revision 1.8  1992/11/22  21:20:45  ahd
  52.  * Use strpool for const string allocation
  53.  *
  54.  * Revision 1.7  1992/11/21  06:17:08  ahd
  55.  * Transmit only one character in response to P (protocol) request
  56.  *
  57.  * Revision 1.6  1992/11/19  03:00:51  ahd
  58.  * drop rcsid
  59.  *
  60.  * Revision 1.5  1992/11/18  03:49:21  ahd
  61.  * Move check of call window to avoid premature lock file overhead
  62.  *
  63.  * Revision 1.4  1992/11/17  13:46:42  ahd
  64.  * If host lookup fails, issue real error message, not malloc failure!
  65.  *
  66.  * Revision 1.3  1992/11/16  02:14:17  ahd
  67.  * Initialize previous directory scanned variable in scandir
  68.  *
  69.  * Revision 1.2  1992/11/15  20:11:07  ahd
  70.  * Clean up modem file support for different protocols
  71.  *
  72.  */
  73.  
  74. /*--------------------------------------------------------------------*/
  75. /*                        system include files                        */
  76. /*--------------------------------------------------------------------*/
  77.  
  78. #include <stdio.h>
  79. #include <stdlib.h>
  80. #include <string.h>
  81. #include <time.h>
  82. #include <ctype.h>
  83.  
  84. /*--------------------------------------------------------------------*/
  85. /*                    UUPC/extended include files                     */
  86. /*--------------------------------------------------------------------*/
  87.  
  88. #include "lib.h"
  89. #include "arpadate.h"
  90. #include "checktim.h"
  91. #include "dcp.h"
  92. #include "dcpfpkt.h"
  93. #include "dcpgpkt.h"
  94. #include "dcplib.h"
  95. #include "dcpsys.h"
  96. #include "export.h"
  97. #include "hlib.h"
  98. #include "hostable.h"
  99. #include "hostatus.h"
  100. #include "modem.h"
  101. #include "lock.h"
  102. #include "nbstime.h"
  103. #include "ndir.h"
  104. #include "ssleep.h"
  105. #include "security.h"
  106. #include "ulib.h"
  107.  
  108. currentfile();
  109.  
  110. Proto Protolst[] = {
  111.        { 'g', ggetpkt, gsendpkt, gopenpk, gclosepk,
  112.               grdmsg,  gwrmsg,   geofpkt, gfilepkt } ,
  113.  
  114.        { 'G', ggetpkt, gsendpkt, Gopenpk, gclosepk,
  115.               grdmsg,  gwrmsg,   geofpkt, gfilepkt } ,
  116.  
  117.        { 'f', fgetpkt, fsendpkt, fopenpk, fclosepk,
  118.               frdmsg,  fwrmsg,   feofpkt, ffilepkt } ,
  119.  
  120.        { 'v', ggetpkt, gsendpkt, vopenpk, gclosepk,
  121.               grdmsg,  gwrmsg,   geofpkt, gfilepkt } ,
  122.    { '\0' }
  123.    };
  124.  
  125. procref  getpkt, sendpkt, openpk, closepk, rdmsg, wrmsg, eofpkt, filepkt;
  126.  
  127. char *flds[60];
  128. int kflds;
  129. static char protocols[5];
  130. static char S_sysline[BUFSIZ];
  131.  
  132. static void setproto(char wanted);
  133.  
  134. static char HostGrade( const char *fname, const char *remote );
  135.  
  136. /****************************************/
  137. /*              Sub Systems             */
  138. /****************************************/
  139.  
  140. /*--------------------------------------------------------------------*/
  141. /*    g e t s y s t e m                                               */
  142. /*                                                                    */
  143. /*    Process a systems file (L.sys) entry.                           */
  144. /*    Null lines or lines starting with '#' are comments.             */
  145. /*--------------------------------------------------------------------*/
  146.  
  147. CONN_STATE getsystem( const char sendgrade )
  148. {
  149.  
  150.    do {
  151.       char *p;
  152.  
  153.       /* flush to next non-comment line */
  154.       if (fgets(S_sysline, BUFSIZ, fsys) == nil(char))
  155.          return CONN_EXIT;
  156.  
  157.       p = S_sysline + strlen( S_sysline );
  158.  
  159. /*--------------------------------------------------------------------*/
  160. /*                     Trim trailing white space                      */
  161. /*--------------------------------------------------------------------*/
  162.  
  163.       while ((p-- > S_sysline) && isspace( *p ))
  164.          *p = '\0';
  165.  
  166.    } while ((*S_sysline == '\0') || (*S_sysline == '#'));
  167.  
  168.    printmsg(8, "sysline=\"%s\"", S_sysline);
  169.  
  170.    kflds = getargs(S_sysline, flds);
  171.  
  172. /*--------------------------------------------------------------------*/
  173. /*              Blitz all the extra fields we don't need              */
  174. /*--------------------------------------------------------------------*/
  175.  
  176.    if ( kflds < FLD_EXPECT )
  177.    {
  178.       printmsg(0,"getsystem:  Invalid system entry "
  179.                  "for %s (missing dial script)",
  180.             flds[FLD_REMOTE] );
  181.  
  182.       return CONN_INITIALIZE;
  183.    }
  184.  
  185.    strcpy(protocols, flds[FLD_PROTO]);
  186.    strcpy(rmtname, flds[FLD_REMOTE]);
  187.  
  188. /*--------------------------------------------------------------------*/
  189. /*                      Summarize the host data                       */
  190. /*--------------------------------------------------------------------*/
  191.  
  192.    printmsg(2,
  193.           "remote=%s, when=%s, device=%s, phone=%s, protocol=%s",
  194.           rmtname, flds[FLD_CCTIME], flds[FLD_TYPE], flds[FLD_PHONE],
  195.           protocols);
  196.  
  197. /*--------------------------------------------------------------------*/
  198. /*                  Determine if the remote is valid                  */
  199. /*--------------------------------------------------------------------*/
  200.  
  201.    hostp = checkreal( rmtname );
  202.    if ( hostp == NULL )
  203.    {
  204.       printmsg(0,"getsystem: Internal lookup error for system %s",
  205.                   rmtname);
  206.       panic();
  207.    }
  208.  
  209. /*--------------------------------------------------------------------*/
  210. /*                   Display the send/expect fields                   */
  211. /*--------------------------------------------------------------------*/
  212.  
  213.    if (debuglevel >= 4) {
  214.       int   i;
  215.       flds[ kflds ] = "";     /* Insure valid send string            */
  216.  
  217.       for (i = FLD_EXPECT; i < kflds; i += 2)
  218.          printmsg(6, "expect [%02d]:\t%s\nsend   [%02d]:\t%s",
  219.             i, flds[i], i + 1, flds[i + 1]);
  220.    }
  221.  
  222. /*--------------------------------------------------------------------*/
  223. /*               Determine if we want to call this host               */
  224. /*                                                                    */
  225. /*    The following if statement breaks down to:                      */
  226. /*                                                                    */
  227. /*       if host not successfully called this run and                 */
  228. /*             (  we are calling all hosts or                         */
  229. /*                we are calling this host or                         */
  230. /*                we are hosts with work and this host has work )     */
  231. /*       then call this host                                          */
  232. /*--------------------------------------------------------------------*/
  233.  
  234.    fwork = nil(FILE);
  235.    if ((hostp->hstatus != called) &&
  236.        (equal(Rmtname, "all") || equal(Rmtname, rmtname) ||
  237.         (equal(Rmtname, "any") &&
  238.         (scandir(rmtname,sendgrade) == XFER_REQUEST))))
  239.     {
  240.  
  241.       if (fwork != nil(FILE)) /* in case matched with scandir     */
  242.          fclose(fwork);
  243.  
  244.       scandir( NULL, sendgrade); /* Reset directory search as well   */
  245.  
  246. /*--------------------------------------------------------------------*/
  247. /*   We want to call the host; is it defined in our security table?   */
  248. /*--------------------------------------------------------------------*/
  249.  
  250.       securep = GetSecurity( hostp );
  251.       if ( securep == NULL )
  252.       {
  253.          printmsg(0,"getsystem: system \"%s\" not defined in "
  254.                     "PERMISSIONS file", hostp->hostname);
  255.          return CONN_INITIALIZE;
  256.       }
  257.  
  258.       memset( &remote_stats, 0, sizeof remote_stats);
  259.       return CONN_CALLUP1;    /* startup this system */
  260.  
  261.    } /* if */
  262.    else
  263.       return CONN_INITIALIZE;    /* Look for next system to process   */
  264.  
  265. } /*getsystem*/
  266.  
  267. /*--------------------------------------------------------------------*/
  268. /*    s y s e n d                                                     */
  269. /*                                                                    */
  270. /*    End UUCP session negotiation                                    */
  271. /*--------------------------------------------------------------------*/
  272.  
  273. CONN_STATE sysend()
  274. {
  275.    char msg[80];
  276.  
  277.    if (hostp->hstatus == inprogress)
  278.       hostp->hstatus = call_failed;
  279.  
  280.    wmsg("OOOOOO", TRUE);
  281.    rmsg(msg, TRUE, 5, sizeof msg);
  282.    wmsg("OOOOOO", TRUE);
  283.    ssleep(2);                 /* Wait for it to be transmitted       */
  284.  
  285.    return CONN_DROPLINE;
  286. } /*sysend*/
  287.  
  288.  
  289. /*--------------------------------------------------------------------*/
  290. /*    w m s g                                                         */
  291. /*                                                                    */
  292. /*    write a ^P type msg to the remote uucp                          */
  293. /*--------------------------------------------------------------------*/
  294.  
  295. void wmsg(char *msg, const boolean synch)
  296. {
  297.  
  298.    if (synch)
  299.       swrite("\0\020", 2);
  300.  
  301.    printmsg( 4, "==> %s%s", synch ? "^p" : "", msg );
  302.  
  303.    swrite(msg, strlen(msg));
  304.  
  305.    if (synch)
  306.       swrite("\0", 1);
  307.  
  308. } /*wmsg*/
  309.  
  310.  
  311. /*--------------------------------------------------------------------*/
  312. /*    r m s g                                                         */
  313. /*                                                                    */
  314. /*    read a ^P msg from UUCP                                         */
  315. /*--------------------------------------------------------------------*/
  316.  
  317. int rmsg(char *msg, const boolean synch, unsigned int msgtime, int max_len)
  318. {
  319.    int i;
  320.    char ch = '?';       /* Initialize to non-zero value  */    /* ahd   */
  321.  
  322. /*--------------------------------------------------------------------*/
  323. /*                        flush until next ^P                         */
  324. /*--------------------------------------------------------------------*/
  325.  
  326.    if (synch == 1)
  327.    {
  328.       do {
  329.  
  330.          if (sread(&ch, 1, msgtime) < 1)
  331.          {
  332.             printmsg(2 ,"rmsg: Timeout waiting for sync");
  333.             return TIMEOUT;
  334.          } /* if */
  335.  
  336.       } while ((ch & 0x7f) != '\020');
  337.    }
  338.  
  339. /*--------------------------------------------------------------------*/
  340. /*   Read until timeout, next newline, or we fill the input buffer    */
  341. /*--------------------------------------------------------------------*/
  342.  
  343.    for (i = 0; (i < max_len) && (ch != '\0'); )
  344.    {
  345.       if (sread(&ch, 1, msgtime) < 1)
  346.       {
  347.          printmsg(1 ,"rmsg: Timeout reading message");
  348.          return TIMEOUT;
  349.       }
  350.  
  351. /*--------------------------------------------------------------------*/
  352. /*               Process backspaces if not in sync mode               */
  353. /*--------------------------------------------------------------------*/
  354.  
  355.       if ((synch != 1) &&
  356.           (ch != '\r') &&
  357.           (ch != '\n') &&
  358.           (ch != '\0') &&
  359.           iscntrl( ch ))
  360.       {
  361.          if ( i && ((ch == 0x7f) || (ch == '\b')))
  362.          {
  363.             i--;
  364.             if ( synch == 2 )
  365.                swrite( "\b \b", 3);
  366.          }
  367.          else {
  368.  
  369.             swrite( "\a", 1 );   /* Beep in response to invalid
  370.                                     cntrl characters, including
  371.                                     extra backspaces                 */
  372.          } /* else */
  373.  
  374.       } /* if */
  375.       else {                  /* else a normal character             */
  376.  
  377. /*--------------------------------------------------------------------*/
  378. /*             Echo the character if requested by caller              */
  379. /*--------------------------------------------------------------------*/
  380.  
  381.          if ( synch == 2 )
  382.             swrite( &ch, 1);
  383.  
  384.          ch &= 0x7f;
  385.          if (ch == '\r' || ch == '\n')
  386.             ch = '\0';
  387.          msg[i++] = ch;
  388.       } /* else */
  389.    }
  390.  
  391.    msg[max_len - 1] = '\0';
  392.    printmsg( 4, "<== %s%s",
  393.                 (synch == 1) ? "^p" : "",
  394.                 msg);
  395.    return strlen(msg);
  396.  
  397. } /*rmsg*/
  398.  
  399.  
  400. /*--------------------------------------------------------------------*/
  401. /*    s t a r t u p _ s e r v e r                                     */
  402. /*                                                                    */
  403. /*    Exchange host and protocol information for a system we called   */
  404. /*--------------------------------------------------------------------*/
  405.  
  406. CONN_STATE startup_server(const char recvgrade )
  407. {
  408.    char msg[80];
  409.    char *s;
  410.  
  411.  
  412.    hostp->hstatus = startup_failed;
  413.  
  414. /*--------------------------------------------------------------------*/
  415. /*    Handle the special case of '*' protocol, which is really our    */
  416. /*    NBS time setting support                                        */
  417. /*--------------------------------------------------------------------*/
  418.  
  419.    if (*protocols == '*')
  420.    {
  421.       if (nbstime())
  422.       {
  423.          hostp->hstatus = called;
  424.          time( &hostp->hstats->lconnect );
  425.       }
  426.  
  427.       return CONN_DROPLINE;
  428.    }
  429.  
  430. /*--------------------------------------------------------------------*/
  431. /*                      Begin normal processing                       */
  432. /*--------------------------------------------------------------------*/
  433.  
  434.    if (rmsg(msg, TRUE, PROTOCOL_TIME, sizeof msg) == TIMEOUT)
  435.    {
  436.       printmsg(0,"Startup: Timeout for first message");
  437.       return CONN_TERMINATE;
  438.    }
  439.  
  440. /*--------------------------------------------------------------------*/
  441. /*              The first message must begin with Shere               */
  442. /*--------------------------------------------------------------------*/
  443.  
  444.    if (!equaln(msg,"Shere",5))
  445.    {
  446.       printmsg(0,"Startup: First message not Shere, was \"%s\"", msg);
  447.       return CONN_TERMINATE;
  448.    }
  449.  
  450. /*--------------------------------------------------------------------*/
  451. /*    The host can send either a simple Shere, or Shere=hostname;     */
  452. /*    we allow either.                                                */
  453. /*--------------------------------------------------------------------*/
  454.  
  455.    if ((msg[5] == '=') && !equaln(&msg[6], rmtname, HOSTLEN))
  456.    {
  457.       printmsg(0,"Startup: Wrong host %s, expected %s",
  458.                &msg[6], rmtname);
  459.       hostp->hstatus = wrong_host;
  460.       return CONN_TERMINATE; /* wrong host */              /* ahd */
  461.    }
  462.  
  463.    /* sprintf(msg, "S%.7s -Q0 -x%d", E_nodename, debuglevel); */
  464.    /* -Q0 -x16 remote debuglevel set */
  465.  
  466.    if (recvgrade != ALL_GRADES)
  467.      sprintf(msg, "S%s -p%c -vgrade=%c", securep->myname,
  468.                   recvgrade, recvgrade );
  469.    else
  470.      sprintf(msg, "S%s", securep->myname );
  471.  
  472.    wmsg(msg, TRUE);
  473.  
  474. /*--------------------------------------------------------------------*/
  475. /*                  Second message is system is okay                  */
  476. /*--------------------------------------------------------------------*/
  477.  
  478.    if (rmsg(msg, TRUE, PROTOCOL_TIME, sizeof msg) == TIMEOUT)
  479.    {
  480.       printmsg(0,"Startup: Timeout for second message");
  481.       return CONN_TERMINATE;
  482.    }
  483.  
  484.    if (!equaln(&msg[1], "OK", 2))
  485.    {
  486.       printmsg(0,"Unexpected second message: %s",&msg[1]);
  487.       return CONN_TERMINATE;
  488.    }
  489.  
  490. /*--------------------------------------------------------------------*/
  491. /*                Third message is protocol exchange                  */
  492. /*--------------------------------------------------------------------*/
  493.  
  494.    if (rmsg(msg, TRUE, PROTOCOL_TIME, sizeof msg) == TIMEOUT)
  495.       return CONN_TERMINATE;
  496.  
  497.    if (*msg != 'P')
  498.    {
  499.       printmsg(0,"Unexpected third message: %s",&msg[1]);
  500.       return CONN_TERMINATE;
  501.    }
  502.  
  503. /*--------------------------------------------------------------------*/
  504. /*                      Locate a common procotol                      */
  505. /*--------------------------------------------------------------------*/
  506.  
  507.    s = strpbrk( protocols, &msg[1] );
  508.    if ( s == NULL )
  509.    {
  510.       printmsg(0,"Startup: No common protocol");
  511.       wmsg("UN", TRUE);
  512.       return CONN_TERMINATE; /* no common protocol */
  513.    }
  514.  
  515. /*--------------------------------------------------------------------*/
  516. /*       While the remote is waiting for us, update our status        */
  517. /*--------------------------------------------------------------------*/
  518.  
  519.    hostp->hstatus = inprogress;
  520.    hostp->hstats->lconnect = time( &remote_stats.lconnect );
  521.  
  522. /*--------------------------------------------------------------------*/
  523. /*              Tell the remote host the protocol to use              */
  524. /*--------------------------------------------------------------------*/
  525.  
  526.    sprintf(msg, "U%c", *s);
  527.    wmsg(msg, TRUE);
  528.  
  529.    setproto(*s);
  530.  
  531. /*--------------------------------------------------------------------*/
  532. /*    The connection is complete; report this and return to caller    */
  533. /*--------------------------------------------------------------------*/
  534.  
  535.    printmsg(0,"%s connected to %s: %ld bps, %c protocol, %c grade",
  536.          E_nodename, rmtname, (long) GetSpeed() , *s, recvgrade );
  537.  
  538.    return CONN_SERVER;
  539.  
  540. } /*startup_server*/
  541.  
  542.  
  543. /*--------------------------------------------------------------------*/
  544. /*    s t a r t u p _ c l i e n t                                     */
  545. /*                                                                    */
  546. /*    Setup a host connection with a system which has called us       */
  547. /*--------------------------------------------------------------------*/
  548.  
  549. CONN_STATE startup_client( char *sendgrade )
  550. {
  551.    char plist[20];
  552.    char msg[80];
  553.    int xdebug = debuglevel;
  554.    char *sysname = rmtname;
  555.    Proto *tproto;
  556.    char *s;
  557.    char *flds[10];
  558.    int  kflds,i;
  559.    char grade = ALL_GRADES;
  560.  
  561. /*--------------------------------------------------------------------*/
  562. /*    Challange the host calling in with the name defined for this    */
  563. /*    login (if available) otherwise our regular node name.  (It's    */
  564. /*    a valid session if the securep pointer is NULL, but this is     */
  565. /*    trapped below in the call to ValidateHost()                     */
  566. /*--------------------------------------------------------------------*/
  567.  
  568.    sprintf(msg, "Shere=%s", securep == NULL ?
  569.                               E_nodename : securep->myname );
  570.    wmsg(msg, TRUE);
  571.  
  572.    if (rmsg(msg, TRUE, PROTOCOL_TIME, sizeof msg) == TIMEOUT)
  573.       return CONN_TERMINATE;
  574.  
  575.    printmsg(2, "1st msg from remote = %s", msg);
  576.  
  577. /*--------------------------------------------------------------------*/
  578. /*             Parse additional flags from remote system              */
  579. /*--------------------------------------------------------------------*/
  580.  
  581.    kflds = getargs(msg,flds);
  582.    strcpy(sysname,&flds[0][1]);
  583.  
  584.    for (i=1; i < kflds; i++)
  585.    {
  586.       if (flds[i][0] != '-')
  587.          printmsg(0,"Invalid argument \"%s\" from system %s",
  588.                     flds[i],
  589.                     sysname);
  590.       else
  591.          switch(flds[i][1])
  592.          {
  593.             case 'Q' :             /* Ignore the remote sequence number   */
  594.                break;
  595.  
  596.             case 'x' :
  597.                sscanf(flds[i], "-x%d", &xdebug);
  598.                break;
  599.  
  600.             case 'p' :
  601.                sscanf(flds[i], "-p%c", &grade);
  602.                break;
  603.  
  604.             case 'v' :
  605.                sscanf(flds[i], "-vgrade=%c", &grade);
  606.                break;
  607.  
  608.             default  :
  609.                printmsg(0,"Invalid argument \"%s\" from system %s",
  610.                           flds[i],
  611.                           sysname);
  612.                break;
  613.          } /* switch */
  614.    } /* for */
  615.  
  616.  
  617.    *sendgrade = min(grade,*sendgrade);
  618.  
  619. /*--------------------------------------------------------------------*/
  620. /*                Verify the remote host name is good                 */
  621. /*--------------------------------------------------------------------*/
  622.  
  623.    hostp = checkreal( sysname );
  624.  
  625.    if ( hostp == BADHOST )
  626.    {
  627.       if (E_anonymous != NULL)
  628.       {
  629.          hostp = checkreal( ANONYMOUS_HOST );      /* Find dummy entry */
  630.  
  631.          if ( hostp == BADHOST )       /* Was it there?              */
  632.             panic();                   /* No --> Drop wing, run in
  633.                                           circles like sky is falling*/
  634.  
  635.          if (!checktime( E_anonymous )) /* Good time to call?         */
  636.          {
  637.             wmsg("RWrong time for anonymous system",TRUE);
  638.             printmsg(0,"Wrong time for anonymous system \"%s\"",sysname);
  639.          }  /* if */
  640.  
  641.          if ( !LockSystem( sysname , B_UUCICO ))
  642.          {
  643.             wmsg("RLCK",TRUE);   /* Odd, we locked anonymous system? */
  644.             return CONN_TERMINATE;
  645.          }
  646.  
  647.          hostp->via = newstr( sysname );
  648.          sysname = ANONYMOUS_HOST;
  649.  
  650.          if ((xdebug > 3)  && (xdebug > debuglevel))
  651.          {
  652.             wmsg("RDebug (-x) level too high for anonymous UUCP - rejected",
  653.                   TRUE);
  654.             printmsg(0,"Excessive debug for anonymous system \"%s\"",sysname);
  655.             return CONN_TERMINATE;
  656.          } /* if (xdebug > 3) */
  657.  
  658.       }    /* if (E_anonymous != NULL) */
  659.       else {
  660.          wmsg("RYou are unknown to me",TRUE);
  661.          printmsg(0,"startup: Unknown host \"%s\"", sysname);
  662.          return CONN_TERMINATE;
  663.       } /* else */
  664.    } /* if ( hostp == BADHOST ) */
  665.    else if ( LockSystem( hostp->hostname , B_UUCICO ))
  666.       hostp->via = hostp->hostname;
  667.    else {
  668.       wmsg("RLCK",TRUE);
  669.       return CONN_TERMINATE;
  670.    } /* else */
  671.  
  672. /*--------------------------------------------------------------------*/
  673. /*                   Correct host for this user id?                   */
  674. /*--------------------------------------------------------------------*/
  675.  
  676.    if ( !ValidateHost( sysname ))
  677.                                           /* Wrong host for user? */
  678.    {                                      /* Yes --> Abort        */
  679.       wmsg("RLOGIN",TRUE);
  680.       printmsg(0,"startup: Access rejected for host \"%s\"", sysname);
  681.       hostp->hstatus = wrong_host;
  682.       return CONN_TERMINATE;
  683.    } /* if */
  684.  
  685.    strcpy(rmtname, hostp->hostname);      /* Make sure we use the
  686.                                              full host name       */
  687.  
  688. /*--------------------------------------------------------------------*/
  689. /*                If we must call the user back, do so                */
  690. /*--------------------------------------------------------------------*/
  691.  
  692.    if (securep->callback)
  693.    {
  694.       wmsg("RCB",TRUE);
  695.       hostp->hstatus = callback_req;
  696.       return CONN_TERMINATE;  /* Really more complex than this       */
  697.    }
  698.  
  699. /*--------------------------------------------------------------------*/
  700. /*                     Set the local debug level                      */
  701. /*--------------------------------------------------------------------*/
  702.  
  703.    if ( xdebug > debuglevel )
  704.    {
  705.       debuglevel = xdebug;
  706.       printmsg(0, "Debuglevel set to %d by remote", debuglevel);
  707.    }
  708.  
  709. /*--------------------------------------------------------------------*/
  710. /*                     Build local protocol list                      */
  711. /*--------------------------------------------------------------------*/
  712.  
  713.    s = plist;
  714.    for (tproto = Protolst; tproto->type != '\0' ; tproto++)
  715.       *s++ = tproto->type;
  716.  
  717.    *s = '\0';                 /* Terminate our string                */
  718.  
  719. /*--------------------------------------------------------------------*/
  720. /*              The host name is good; get the protocol               */
  721. /*--------------------------------------------------------------------*/
  722.  
  723.    wmsg("ROK", TRUE);
  724.  
  725.    sprintf(msg, "P%s", plist);
  726.    wmsg(msg, TRUE);
  727.  
  728.    if (rmsg(msg, TRUE, PROTOCOL_TIME, sizeof msg) == TIMEOUT)
  729.       return CONN_TERMINATE;
  730.  
  731.    if (msg[0] != 'U')
  732.    {
  733.       printmsg(0,"Unexpected second message: %s", msg);
  734.       return CONN_TERMINATE;
  735.    }
  736.  
  737.    if (strchr(plist, msg[1]) == nil(char))
  738.    {
  739.       printmsg(0,"startup: Host %s does not support our protocols",
  740.             rmtname );
  741.       return CONN_TERMINATE;
  742.    }
  743.  
  744.    setproto(msg[1]);
  745.  
  746. /*--------------------------------------------------------------------*/
  747. /*            Report that we connected to the remote host             */
  748. /*--------------------------------------------------------------------*/
  749.  
  750.    printmsg(0,"%s called by %s: %ld bps, %c protocol, %c grade",
  751.          E_nodename,
  752.          hostp->via,
  753.          (long) GetSpeed(),
  754.          msg[1],
  755.          *sendgrade );
  756.  
  757.    if ( hostp == BADHOST )
  758.       panic();
  759.  
  760.    hostp->hstatus = inprogress;
  761.    hostp->hstats->lconnect = time( &remote_stats.lconnect );
  762.  
  763.    return CONN_CLIENT;
  764.  
  765. } /*startup_client*/
  766.  
  767.  
  768. /*--------------------------------------------------------------------*/
  769. /*    s e t p r o t o                                                 */
  770. /*                                                                    */
  771. /*    set the protocol to be used                                     */
  772. /*--------------------------------------------------------------------*/
  773.  
  774. static void setproto(char wanted)
  775. {
  776.    Proto *tproto;
  777.  
  778.    for (tproto = Protolst;
  779.       tproto->type != '\0' && tproto->type != wanted;
  780.       tproto++) {
  781.       printmsg(3, "setproto: wanted '%c', have '%c'", wanted, tproto->type);
  782.    }
  783.  
  784.    if (tproto->type == '\0') {
  785.       printmsg(0, "setproto: You said I have protocol '%c' but I cant find it!",
  786.             wanted);
  787.       panic();
  788.    }
  789.  
  790.    printmsg(3, "setproto: wanted '%c', have '%c'", wanted, tproto->type);
  791.  
  792.    getpkt  = tproto->getpkt;
  793.    sendpkt = tproto->sendpkt;
  794.    openpk  = tproto->openpk;
  795.    closepk = tproto->closepk;
  796.    rdmsg   = tproto->rdmsg;
  797.    wrmsg   = tproto->wrmsg;
  798.    eofpkt  = tproto->eofpkt;
  799.    filepkt = tproto->filepkt;
  800.  
  801. } /*setproto*/
  802.  
  803.  
  804. /*--------------------------------------------------------------------*/
  805. /*    s c a n d i r                                                   */
  806. /*                                                                    */
  807. /*    Scan spooling directory for C.* files for the remote host       */
  808. /*    (rmtname)                                                       */
  809. /*--------------------------------------------------------------------*/
  810.  
  811. XFER_STATE scandir(char *remote, const char grade )
  812. {
  813.    static DIR *dirp;
  814.    static char *SaveRemote = NULL;
  815.    static char remotedir[FILENAME_MAX];
  816.  
  817.    struct direct *dp;
  818.  
  819. /*--------------------------------------------------------------------*/
  820. /*          Determine if we must restart the directory scan           */
  821. /*--------------------------------------------------------------------*/
  822.  
  823.    if (fwork != NULL )
  824.    {
  825.       fclose( fwork );
  826.       fwork = NULL;
  827.    }
  828.  
  829.    if ( (remote == NULL) || ( SaveRemote == NULL ) ||
  830.         !equaln(remote, SaveRemote, sizeof SaveRemote - 1 ) )
  831.    {
  832.       if ( SaveRemote != NULL ) /* Clean up old directory? */
  833.       {                          /* Yes --> Do so           */
  834.          closedir(dirp);
  835.          SaveRemote = NULL;
  836.       } /* if */
  837.  
  838.       if ( remote == NULL )      /* Clean up only, no new search? */
  839.          return XFER_NOLOCAL;    /* Yes --> Return to caller      */
  840.  
  841.       sprintf(remotedir,"%s/%.8s/C", E_spooldir, remote);
  842.       if ((dirp = opendir(remotedir)) == nil(DIR))
  843.       {
  844.          printmsg(2, "scandir: couldn't opendir() %s", remotedir);
  845.          return XFER_NOLOCAL;
  846.       } /* if */
  847.  
  848.       SaveRemote = newstr( remote );
  849.                               /* Flag we have an active search    */
  850.  
  851.    } /* if */
  852.  
  853. /*--------------------------------------------------------------------*/
  854. /*              Look for the next file in the directory               */
  855. /*--------------------------------------------------------------------*/
  856.  
  857.    while ((dp = readdir(dirp)) != nil(struct direct))
  858.    {
  859.       sprintf(workfile, "%s/%s", remotedir, dp->d_name);
  860.  
  861.       if ( HostGrade( workfile, remote ) > grade )
  862.          printmsg(5, "scandir: skipped \"%s\" (grade %c not met)",             workfile,
  863.                       grade );
  864.       else if ((fwork = FOPEN(workfile, "r", TEXT)) == nil(FILE))
  865.       {
  866.          printmsg(0,"scandir: open failed for %s",workfile);
  867.          SaveRemote = NULL;
  868.          return XFER_ABORT;   /* Very bad, since we just read its
  869.                                  directory entry!                 */
  870.       }
  871.       else {
  872.          setvbuf( fwork, NULL, _IONBF, 0);
  873.          printmsg(5, "scandir: matched \"%s\"",workfile);
  874.          return XFER_REQUEST; /* Return success                   */
  875.       }
  876.  
  877.    } /* while */
  878.  
  879. /*--------------------------------------------------------------------*/
  880. /*     No hit; clean up after ourselves and return to the caller      */
  881. /*--------------------------------------------------------------------*/
  882.  
  883.    printmsg(5, "scandir: \"%s\" not matched", remotedir);
  884.    closedir(dirp);
  885.    SaveRemote = NULL;
  886.    return XFER_NOLOCAL;
  887.  
  888. } /*scandir*/
  889.  
  890.  
  891. /*--------------------------------------------------------------------*/
  892. /*    H o s t G r a d e                                               */
  893. /*                                                                    */
  894. /*    Return host grade of a call file                                */
  895. /*--------------------------------------------------------------------*/
  896.  
  897. static char HostGrade( const char *fname, const char *remote )
  898. {
  899.  
  900.    char tempname[FILENAME_MAX];
  901.    size_t len = strlen( remote );
  902.  
  903.    exportpath( tempname, fname, remote );
  904.  
  905.    if ( len > HOSTLEN )
  906.       len = HOSTLEN;
  907.  
  908.    return tempname[len + 2 ];
  909.  
  910. } /* HostGrade */
  911.  
  912.  
  913. /*--------------------------------------------------------------------*/
  914. /*    C a l l W i n d o w                                             */
  915. /*                                                                    */
  916. /*    Determine if we can call a system                               */
  917. /*--------------------------------------------------------------------*/
  918.  
  919. boolean CallWindow( const char callgrade )
  920. {
  921.  
  922. /*--------------------------------------------------------------------*/
  923. /*      Determine if the window for calling this system is open       */
  924. /*--------------------------------------------------------------------*/
  925.  
  926.    if ( !callgrade && equal(flds[FLD_CCTIME],"Never" ))
  927.    {
  928.       hostp->hstatus = wrong_time;
  929.       return FALSE;
  930.    }
  931.  
  932. /*--------------------------------------------------------------------*/
  933. /*    Check the time of day and whether or not we should call now.    */
  934. /*                                                                    */
  935. /*    If calling a system to set the clock and we determine the       */
  936. /*    system clock is bad (we fail the sanity check of the last       */
  937. /*    connected a host to being in the future), then we ignore the    */
  938. /*    time check field.                                               */
  939. /*--------------------------------------------------------------------*/
  940.  
  941.    if (!callgrade)
  942.    {
  943.       if ((*flds[FLD_PROTO] != '*') ||       /* Not setting clock?   */
  944.           ((hostp->hstats->ltime >  630720000L )))
  945.                                              /* Clock okay?          */
  946.       {                                      /* Yes--> Return        */
  947.          hostp->hstatus = wrong_time;
  948.          time(&hostp->hstats->ltime);  /* Save time of last attempt to call   */
  949.          return FALSE;
  950.       }
  951.    } /* if */
  952.  
  953. /*--------------------------------------------------------------------*/
  954. /*       We pass the time check                                       */
  955. /*--------------------------------------------------------------------*/
  956.  
  957.    return TRUE;
  958.  
  959. } /* CallWindow */
  960.